/* 
 * File:   ntfs.h
 * Author: lishang
 *
 * Created on 2018年3月27日, 下午5:20
 */
#include <linux/types.h>

#ifndef NTFS_H
#define NTFS_H
 //#pragma pack(1);
#pragma pack(push,1)

typedef __u8 u8;
typedef __s8 s8;
typedef __le16  le16;
typedef __le32 le32;
typedef __le64   le64;
typedef __u64 __bitwise sle64;

typedef struct {
	u8  jump[3];			/* Irrelevant (jump to boot up code).*/
        	char oem_id[8];			/* Magic "NTFS    ". */
	//le64 oem_id;			/* Magic "NTFS    ". */
	le16 bytes_per_sector;		/* Size of a sector in bytes.每个扇区的字节数 */
	u8  sectors_per_cluster;	/* Size of a cluster in sectors. 每簇扇区数*/
        
	le16 reserved_sectors;		/* zero */
	u8  fats;			/* zero */
	le16 root_entries;		/* zero */
	le16 sectors;			/* zero */
        
/* 0x15 */	u8  media_type;			/* 0xf8 = hard disk */
	le16 sectors_per_fat;		/* zero */
	le16 sectors_per_track;		/* irrelevant */
	le16 heads;			/* irrelevant */
	le32 hidden_sectors;		/* zero */
	le32 large_sectors;		/* zero */
	u8  unused[4];			/* zero, NTFS diskedit.exe states that
					   this is actually:
						__u8 physical_drive;	// 0x80
						__u8 current_head;	// zero
						__u8 extended_boot_signature;
									// 0x80
						__u8 unused;		// zero
					 */
/*0x28*/sle64 number_of_sectors;	/* Number of sectors in volume. Gives  扇区总数 
					   maximum volume size of 2^63 sectors.
					   Assuming standard sector size of 512
					   bytes, the maximum byte size is
					   approx. 4.7x10^21 bytes. (-; */
	sle64 mft_lcn;			/* Cluster location of mft data.     $MFT开始的逻辑簇号*/
	sle64 mftmirr_lcn;		/* Cluster location of copy of mft. */
	s8  clusters_per_mft_record;	/* Mft record size in clusters. 每个MFT记录簇数 */
	u8  reserved0[3];		/* zero */
	s8  clusters_per_index_record;	/* Index block size in clusters. */
	u8  reserved1[3];		/* zero */
	le64 volume_serial_number;	/* Irrelevant (serial number). */
	le32 checksum;			/* Boot sector checksum. */
/*0x54*/u8  bootstrap[426];		/* Irrelevant (boot up code). */
	le16 end_of_sector_marker;	/* End of bootsector magic. Always is
					   0xaa55 in little endian. */
/* sizeof() = 512 (0x200) bytes */
} NTFS_BOOT_SECTOR ;


typedef struct {
/*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
	le32 magic;	/* Usually the magic is "FILE". */
	le16 usa_ofs;		/* See NTFS_RECORD definition above. */
	le16 usa_count;		/* See NTFS_RECORD definition above. */

/*  8*/	le64 lsn;		/* $LogFile sequence number for this record.
				   Changed every time the record is modified. */
/* 16*/	le16 sequence_number;	/* Number of times this mft record has been
				   reused. (See description for MFT_REF
				   above.) NOTE: The increment (skipping zero)
				   is done when the file is deleted. NOTE: If
				   this is zero it is left zero. */
/* 18*/	le16 link_count;	/* Number of hard links, i.e. the number of
				   directory entries referencing this record.
				   NOTE: Only used in mft base records.
				   NOTE: When deleting a directory entry we
				   check the link_count and if it is 1 we
				   delete the file. Otherwise we delete the
				   FILE_NAME_ATTR being referenced by the
				   directory entry from the mft record and
				   decrement the link_count.
				   FIXME: Careful with Win32 + DOS names! */
/* 20*/	le16 attrs_offset;	/* Byte offset to the first attribute in this   第一个属性的偏移位置  
				   mft record from the start of the mft record.
				   NOTE: Must be aligned to 8-byte boundary. */
/* 22*/	le16 flags;	/* Bit array of MFT_RECORD_FLAGS. When a file       类型 1表示文件 2 表是目录  
				   is deleted, the MFT_RECORD_IN_USE flag is
				   set to zero. */
/* 24*/	le32 bytes_in_use;	/* Number of bytes used in this mft record.    文件记录的实际大小
				   NOTE: Must be aligned to 8-byte boundary. */
/* 28*/	le32 bytes_allocated;	/* Number of bytes allocated for this mft   文件记录的分配大小  
				   record. This should be equal to the mft
				   record size. */
/* 32*/	le64 base_mft_record;/* This is zero for base mft records.
				   When it is not zero it is a mft reference
				   pointing to the base mft record to which
				   this record belongs (this is then used to
				   locate the attribute list attribute present
				   in the base record which describes this
				   extension record and hence might need
				   modification when the extension record
				   itself is modified, also locating the
				   attribute list also means finding the other
				   potential extents, belonging to the non-base
				   mft record). */
/* 40*/	le16 next_attr_instance;/* The instance number that will be assigned to
				   the next attribute added to this mft record.
				   NOTE: Incremented each time after it is used.
				   NOTE: Every time the mft record is reused
				   this number is set to zero.  NOTE: The first
				   instance number is always 0. */
/* The below fields are specific to NTFS 3.1+ (Windows XP and above): */
/* 42*/ le16 reserved;		/* Reserved/alignment. */
/* 44*/ le32 mft_record_number;	/* Number of this mft record.   本MFT记录号 */
/* sizeof() = 48 bytes */
/*
 * When (re)using the mft record, we place the update sequence array at this
 * offset, i.e. before we start with the attributes.  This also makes sense,
 * otherwise we could run into problems with the update sequence array
 * containing in itself the last two bytes of a sector which would mean that
 * multi sector transfer protection wouldn't work.  As you can't protect data
 * by overwriting it since you then can't get it back...
 * When reading we obviously use the data from the ntfs record header.
 */
} __attribute__ ((__packed__)) MFT_RECORD;


/*
 * Attribute record header. Always aligned to 8-byte boundary.
 */
typedef struct {
/*Ofs*/
/*  0*/	le32 type;		/* The (32-bit) type of the attribute.   属性类型   10标准信息，20属性列表，30文件名，80数据，90索引根*/   
/*  4*/	le32 length;		/* Byte size of the resident part of the   属性长度  
				   attribute (aligned to 8-byte boundary).
				   Used to get to the next attribute. */
/*  8*/	u8 non_resident;	/* If 0, attribute is resident.             非常驻标志 0常驻 1非常驻
				   If 1, attribute is non-resident. */
/*  9*/	u8 name_length;		/* Unicode character size of name of attribute.
				   0 if unnamed. */
/* 0x0a*/	le16 name_offset;	/* If name_length != 0, the byte offset to the       名称偏移 80属性常驻下就是文件内容开始的位置
				   beginning of the name from the attribute
				   record. Note that the name is stored as a
				   Unicode string. When creating, place offset
				   just at the end of the record header. Then,
				   follow with attribute value or mapping pairs
				   array, resident and non-resident attributes
				   respectively, aligning to an 8-byte
				   boundary. */
/* 0x0c*/	le16 flags;	/* Flags describing the attribute. */
/* 0x0e*/	le16 instance;		/* The instance of this attribute record. This
				   number is unique within this mft record (see
				   MFT_RECORD/next_attribute_instance notes in
				   in mft.h for more details). */
/* 16*/	union {
		/* Resident attributes. */
		struct {
/* 16 */		le32 value_length;/* Byte size of attribute value.  属性长度 */
/* 20 */		le16 value_offset;/* Byte offset of the attribute
					     value from the start of the
					     attribute record. When creating,
					     align to 8-byte boundary if we
					     have a name present as this might
					     not have a length of a multiple
					     of 8-bytes. */
/* 22 */		u8 flags; /* See above. */
/* 23 */		s8 reserved;	  /* Reserved/alignment to 8-byte
					     boundary. */
		} __attribute__ ((__packed__)) resident;
		/* Non-resident attributes. */
		struct {
/* 16*/			sle64 lowest_vcn;/* Lowest valid virtual cluster number
				for this portion of the attribute value or
				0 if this is the only extent (usually the
				case). - Only when an attribute list is used
				does lowest_vcn != 0 ever occur. */
/* 24*/			sle64 highest_vcn;/* Highest valid vcn of this extent of
				the attribute value. - Usually there is only one
				portion, so this usually equals the attribute
				value size in clusters minus 1. Can be -1 for
				zero length files. Can be 0 for "single extent"
				attributes. */
/* 32*/			le16 mapping_pairs_offset; /* Byte offset from the   数据运行的偏移
				beginning of the structure to the mapping pairs
				array which contains the mappings between the
				vcns and the logical cluster numbers (lcns).
				When creating, place this at the end of this
				record header aligned to 8-byte boundary. */
/* 34*/			u8 compression_unit; /* The compression unit expressed
				as the log to the base 2 of the number of
				clusters in a compression unit.  0 means not
				compressed.  (This effectively limits the
				compression unit size to be a power of two
				clusters.)  WinNT4 only uses a value of 4.
				Sparse files have this set to 0 on XPSP2. */
/* 35*/			u8 reserved[5];		/* Align to 8-byte boundary. */
/* The sizes below are only used when lowest_vcn is zero, as otherwise it would
   be difficult to keep them up-to-date.*/
/* 40*/			sle64 allocated_size;	/* Byte size of disk space
				allocated to hold the attribute value. Always
				is a multiple of the cluster size. When a file
				is compressed, this field is a multiple of the
				compression block size (2^compression_unit) and
				it represents the logically allocated space
				rather than the actual on disk usage. For this
				use the compressed_size (see below). */
/* 48*/			sle64 data_size;	/* Byte size of the attribute
				value. Can be larger than allocated_size if
				attribute value is compressed or sparse. */
/* 56*/			sle64 initialized_size;	/* Byte size of initialized
				portion of the attribute value. Usually equals
				data_size. */
/* sizeof(uncompressed attr) = 64*/
/* 64*/			sle64 compressed_size;	/* Byte size of the attribute
				value after compression.  Only present when
				compressed or sparse.  Always is a multiple of
				the cluster size.  Represents the actual amount
				of disk space being used on the disk. */
/* sizeof(compressed attr) = 72*/
		} __attribute__ ((__packed__)) non_resident;
	} __attribute__ ((__packed__)) data;
} __attribute__ ((__packed__)) ATTR_RECORD;



/*
 * Attribute record header. Always aligned to 8-byte boundary.
 */
typedef struct {
/*Ofs*/
/*  0*/	le32 type;		/* The (32-bit) type of the attribute.   属性类型   10标准信息，20属性列表，30文件名，80数据，90索引根*/   
/*  4*/	le32 length;		/* Byte size of the resident part of the   属性长度  
				   attribute (aligned to 8-byte boundary).
				   Used to get to the next attribute. */
/*  8*/	u8 non_resident;	/* If 0, attribute is resident.             非常驻标志 0常驻 1非常驻
				   If 1, attribute is non-resident. */
/*  9*/	u8 name_length;		/* Unicode character size of name of attribute.
				   0 if unnamed. */
/* 0x0a*/	le16 name_offset;	/* If name_length != 0, the byte offset to the       名称偏移 80属性常驻下就是文件内容开始的位置
				   beginning of the name from the attribute
				   record. Note that the name is stored as a
				   Unicode string. When creating, place offset
				   just at the end of the record header. Then,
				   follow with attribute value or mapping pairs
				   array, resident and non-resident attributes
				   respectively, aligning to an 8-byte
				   boundary. */
/* 0x0c*/	le16 flags;	/* Flags describing the attribute. */
/* 0x0e*/	le16 instance;		/* The instance of this attribute record. This
				   number is unique within this mft record (see
				   MFT_RECORD/next_attribute_instance notes in
				   in mft.h for more details). */
} __attribute__ ((__packed__)) ATTR_COMMON;

typedef struct {    //0x10
                     ATTR_COMMON common_head;  
/* 0x10 */  le32 value_length;                       //属性长度
/* 0x14 */  le16 value_offsite;                       
/* 0x16 */  u8  index_flag;                       
/* 0x17 */  u8  zero;                                               /* zero */
/*  0x18*/	sle64 creation_time;		/* Time file was created. Updated when
					   a filename is changed(?). */
/*  0x20*/	sle64 last_data_change_time;	/* Time the data attribute was last
					   modified. */
/* 0x28*/	sle64 last_mft_change_time;	/* Time this mft record was last
					   modified. */
/* 0x30*/	sle64 last_access_time;		/* Approximate time when the file was
					   last accessed (obviously this is not
					   updated on read-only volumes). In
					   Windows this is only updated when
					   accessed if some time delta has
					   passed since the last update. Also,
					   last access time updates can be
					   disabled altogether for speed. */
/* 0x38*/	le32 file_attributes; /* Flags describing the file. */
} __attribute__ ((__packed__)) STANDARD_INFORMATION;


typedef struct {    //0x30
                     ATTR_COMMON common_head;  
/* 0x10 */  le32 value_length;                       //属性长度
/* 0x14 */  le16 value_offsite;                       
/* 0x16 */  u8  index_flag;                       
/* 0x17 */  u8  zero;                                               /* zero */

/*hex ofs*/
/*  0x18*/	le64 parent_directory;	/* Directory this filename is   父目录的文件参考号  
					   referenced from. */
/*  0x20*/	sle64 creation_time;		/* Time file was created. 文件创建时间*/
/* 0x28*/	sle64 last_data_change_time;	/* Time the data attribute was last  文件修改时间
					   modified. */
/* 0x30*/	sle64 last_mft_change_time;	/* Time this mft record was last
					   modified. */
/* 0x35*/	sle64 last_access_time;		/* Time this mft record was last  最后一次访问时间  
					   accessed. */
/* 0x40*/	sle64 allocated_size;		/* Byte size of on-disk allocated space    文件分配大小   单位字节 
					   for the unnamed data attribute.  So
					   for normal $DATA, this is the
					   allocated_size from the unnamed
					   $DATA attribute and for compressed
					   and/or sparse $DATA, this is the
					   compressed_size from the unnamed
					   $DATA attribute.  For a directory or
					   other inode without an unnamed $DATA
					   attribute, this is always 0.  NOTE:
					   This is a multiple of the cluster
					   size. */
/* 0x48*/	sle64 data_size;		/* Byte size of actual data in unnamed 文件实际大小  
					   data attribute.  For a directory or
					   other inode without an unnamed $DATA
					   attribute, this is always 0. */
/* 38*/	le32 file_attributes;	/* Flags describing the file. */
/* 3c*/	union {
	/* 3c*/	struct {
		/* 3c*/	le16 packed_ea_size;	/* Size of the buffer needed to
						   pack the extended attributes
						   (EAs), if such are present.*/
		/* 3e*/	le16 reserved;		/* Reserved for alignment. */
		} __attribute__ ((__packed__)) ea;
	/* 3c*/	struct {
		/* 3c*/	le32 reparse_point_tag;	/* Type of reparse point,
						   present only in reparse
						   points and only if there are
						   no EAs. */
		} __attribute__ ((__packed__)) rp;
	} __attribute__ ((__packed__)) type2;
/* 40*/	u8 file_name_length;			/* Length of file name in
						   (Unicode) characters. */
/* 41*/	u8 file_name_type;	/* Namespace of the file name.*/
/* 42*/	le16 file_name[1];			/* File name in Unicode. 文件名  */
} __attribute__ ((__packed__)) FILE_NAME_ATTR;

typedef struct {/* 0x80 */
                                    ATTR_COMMON common_head;  
/* 0x10 */                 le64 lowest_vcn;/* 开始的vcn */
/* 0x18 */                 le64 highest_vcn;/*结束的vcn */
/* 0x20*/                 le16 mapping_pairs_offset; /* 数据运行偏移 */
/* 0x22*/                 u8 compression_unit; /* The compression unit expressed
				as the log to the base 2 of the number of
				clusters in a compression unit.  0 means not
				compressed.  (This effectively limits the
				compression unit size to be a power of two
				clusters.)  WinNT4 only uses a value of 4.
				Sparse files have this set to 0 on XPSP2. */
/* 0x24 */			u8 reserved[5];		/* Align to 8-byte boundary. */
/* The sizes below are only used when lowest_vcn is zero, as otherwise it would
   be difficult to keep them up-to-date.*/
/* 0x28*/			sle64 allocated_size;	/* Byte size of disk space
				allocated to hold the attribute value. Always
				is a multiple of the cluster size. When a file
				is compressed, this field is a multiple of the
				compression block size (2^compression_unit) and
				it represents the logically allocated space
				rather than the actual on disk usage. For this
				use the compressed_size (see below). */
/* 0x30*/			sle64 data_size;	/* Byte size of the attribute  属性的实际大小
				value. Can be larger than allocated_size if
				attribute value is compressed or sparse. */
/* 0x38*/			sle64 initialized_size;	/* Byte size of initialized     属性的压缩大小
				portion of the attribute value. Usually equals
				data_size. */
/* sizeof(uncompressed attr) = 64*/
/* 0x40*/			char run[1];	/* Byte size of the attribute
				value after compression.  Only present when
				compressed or sparse.  Always is a multiple of
				the cluster size.  Represents the actual amount
				of disk space being used on the disk. */
/* sizeof(compressed attr) = 72*/
} __attribute__ ((__packed__)) FILE_DATA_ATTR;


typedef struct { /* 0xA0 */
/*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
	u8 magic[4];	/* Magic is "INDX". */
	le16 usa_ofs;		/* See NTFS_RECORD definition. */
	le16 usa_count;		/* See NTFS_RECORD definition. */

/*  8*/	sle64 lsn;		/* $LogFile sequence number of the last
				   modification of this index block. */
/* 0x10*/	sle64 index_block_vcn;	/* Virtual cluster number of the index block.
				   If the cluster_size on the volume is <= the
				   index_block_size of the directory,
				   index_block_vcn counts in units of clusters,
				   and in units of sectors otherwise. */
/* 0x18*/   le32 entries_offset;		/* Byte offset to first INDEX_ENTRY
					   aligned to 8-byte boundary. */
/* 0x1c*/	le32 index_length;		/* Data size of the index in bytes,
					   i.e. bytes used from allocated
					   size, aligned to 8-byte boundary. */
/* 0x20*/	le32 allocated_size;		/* Byte size of this index (block),
					   multiple of 8 bytes. */
	/* NOTE: For the index root attribute, the above two numbers are always
	   equal, as the attribute is resident and it is resized as needed. In
	   the case of the index allocation attribute the attribute is not
	   resident and hence the allocated_size is a fixed value and must
	   equal the index_block_size specified by the INDEX_ROOT attribute
	   corresponding to the INDEX_ALLOCATION attribute this INDEX_BLOCK
	   belongs to. */
/* 0x24*/	u8 flags;	/* Bit field of INDEX_HEADER_FLAGS. */
	u8 reserved[3];			/* Reserved/align to 8-byte boundary. */
                     u8 null[0x18];   
/* 0x40 */  char item0[1];
} __attribute__ ((__packed__)) INDEX_BLOCK;

typedef unsigned char UCHAR;
struct IndexHeader  /* 0x90 */
{
    ATTR_COMMON common_head;
/*0x10*/
    le32 index_length;	
    le16 allocated_size;		
    u8 flags;	/* Bit field of INDEX_HEADER_FLAGS. */
    u8 reserved;			/* Reserved/align to 8-byte boundary. */
/*0x18*/
    UCHAR attr_name[8];             //  属性名 unicode $I30 
/*0x20*/
    UCHAR type[4];             //  属性类型 
    UCHAR checkRule[4];        // 校对规则 
    UCHAR allocSize[4];        // 索引项分配大小 
    UCHAR CluPerIdx;           // 每索引记录的簇数
    UCHAR noUse01[3];          // 填充 

/*0x30*/
    UCHAR firstIdxOffset[4];    // 第一个索引项偏移 
    UCHAR idxTotalSize[4];      // *索引项总大小 
    UCHAR indxAllocSize[4];     // *索引项分配大小 
/* 0x3C*/    
    UCHAR flag;                 // *标志    0 小索引使用与索引根 1 大索引适用与索引分配
    UCHAR noUse02[3];
    UCHAR item0[1];
};
// 一般小目录在90属性中有常驻目录项，目录项的结构与INDX缓存中的目录项一样
struct IndexItem
{    
    UCHAR MFTnum[8];                 // 文件的 MFT 记录号，前6B是MFT编号,用于定位此文件记录
    le16 ItemLen;              // 索引项大小
    UCHAR IndexIdentifier[2];      // 索引标志 R
    UCHAR isNode[2];                // 1---此索引包含一个子节点，0---此为最后一项 
    UCHAR noUse03[2];               // 填充
    UCHAR FMFTnum[8];               // 父目录 MFT文件参考号 0x05表示根目录 
    UCHAR CreateTime[8];            //文件创建时间
    UCHAR fileModifyTime[8];        //文件修改时间
    UCHAR MFTModifyTime[8];         //文件记录最后修改时间
    UCHAR LastVisitTime[8];         //文件最后访问时间
    UCHAR FileAllocSize[8];         //文件分配大小 (B)
    UCHAR FileRealSize[8];          //文件实际大小 (B)
    UCHAR FileIdentifier[8];        //文件标志
    UCHAR FileNameLen;              //文件名长度
    UCHAR FileNameSpace;           //文件名命名空间
//---- 0x52 --- 
    UCHAR FileName[1];                     // 文件名 (末尾填满 8 字节)
//    UCHAR nextItemVCN[8];           // 下一项的 VCN (有子节点才有)
};

typedef struct {
    long postion;   //扇区
    long index;    
    long size; //扇区个数 
} MFT_BLOCK;

//#pragma pack(pop)
#endif /* NTFS_H */

